package com.ponhu.ea2.stockcenter.provider.service.rpc.impl;

import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.ponhu.ea2.stockcenter.enums.DefinedSystem;
import com.ponhu.ea2.stockcenter.provider.constants.CommonConstant;
import com.ponhu.ea2.stockcenter.provider.entity.StockInventoryReal;
import com.ponhu.ea2.stockcenter.provider.entity.StockInventoryUnreal;
import com.ponhu.ea2.stockcenter.provider.mapper.StockInventoryRealMapper;
import com.ponhu.ea2.stockcenter.provider.service.biz.stocksales.SalesStockChangeCoreHandler;
import com.ponhu.ea2.stockcenter.provider.service.entity.StockInventoryRealService;
import com.ponhu.ea2.stockcenter.provider.service.entity.StockInventoryUnrealService;
import com.ponhu.ea2.stockcenter.provider.support.exception.StockRuntimeException;
import com.ponhu.ea2.stockcenter.provider.support.vo.GoodsCenterInventoryVO;
import com.ponhu.ea2.stockcenter.provider.support.vo.InventoryInfoVO;
import com.ponhu.ea2.stockcenter.service.bms.StockForGoodsCenterService;
import com.ponhu.ea2.stockcenter.vo.ReturnResponseBean;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.DubboService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

import static com.ponhu.ea2.stockcenter.enums.ResponseCodeEnum.*;
import static com.ponhu.ea2.stockcenter.provider.constants.CommonConstant.INIT_STATUS.FINISHED;
import static com.ponhu.ea2.stockcenter.provider.support.enums.StockChangeInnerEventEnum.ADD_VIRTUAL_SALES_STOCK;
import static com.ponhu.ea2.stockcenter.provider.support.enums.StockChangeInnerEventEnum.DELETE_VIRTUAL_SALES_STOCK;

/**
 * @author Wang
 * @date 2021/10/20 4:01 下午
 */
@Slf4j
@DubboService(version = "1.0.0", interfaceClass = StockForGoodsCenterService.class, timeout = 60000)
public class StockForGoodsCenterServiceImpl implements StockForGoodsCenterService {

    @Autowired
    private StockInventoryRealService stockInventoryRealService;
    @Autowired
    private StockInventoryUnrealService stockInventoryUnrealService;
    @Autowired
    private StockInventoryRealMapper stockInventoryRealMapper;
    @Autowired
    private SalesStockChangeCoreHandler salesStockChangeCoreHandler;

    /**
     * 创建并初始化虚拟类货品库存数据
     *
     * @param goodsId       商品Id
     * @param inventoryId   货品Id
     * @param inventoryCode 货品编码
     * @param stockNumber   库存数量
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public boolean createAndInitUnRealStockData(Long goodsId, Long inventoryId, String inventoryCode, int stockNumber) {
        if (!checkParamsIsCorrect(goodsId, inventoryId, inventoryCode, stockNumber)) {
            log.error("初始化虚拟类库存失败，参数不正确。goodsId:{}, inventoryId: {}, inventoryCode: {}, stockNumber{}",
                    goodsId, inventoryId, inventoryCode, stockNumber);
            throw new StockRuntimeException(PARAMS_INCORRECT_EXCEPTION_900003);
        }

        //初始化实物类库存
        stockInventoryRealService.createAndInitStockData(goodsId, inventoryId, inventoryCode, 0);
        //初始化虚拟类库存
        return stockInventoryUnrealService.createAndInitStockData(goodsId, inventoryId, inventoryCode, stockNumber);
    }

    /**
     * 创建并初始化实物类库存数据
     *
     * @param goodsId       商品Id
     * @param inventoryId   货品Id
     * @param inventoryCode 货品编码
     * @param stockNumber   库存数量
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public boolean createAndInitRealStockData(Long goodsId, Long inventoryId, String inventoryCode, int stockNumber) {
        if (!checkParamsIsCorrect(goodsId, inventoryId, inventoryCode, stockNumber)) {
            log.error("初始化虚拟类库存失败，参数不正确。goodsId:{}, inventoryId: {}, inventoryCode: {}, stockNumber{}",
                    goodsId, inventoryId, inventoryCode, stockNumber);
            throw new StockRuntimeException(PARAMS_INCORRECT_EXCEPTION_900003);
        }

        //初始化实物类库存
        return stockInventoryRealService.createAndInitStockData(goodsId, inventoryId, inventoryCode, stockNumber);
    }

    /**
     * 添加一个虚拟可售库存
     *
     * @param inventoryCodeList
     * @return
     */
    @Override
    public ReturnResponseBean<Boolean> addOneVirtualSalesStockData(List<String> inventoryCodeList) {
        List<StockInventoryUnreal> inventoryUnrealList = checkInventoryListIfExists(inventoryCodeList);
        List<StockInventoryUnreal> collect = inventoryUnrealList.stream().map(i -> i.setSaleStockNum(i.getSaleStockNum() + 1)).collect(Collectors.toList());
        stockInventoryUnrealService.updateBatchById(collect);

        //记录日志
        List<InventoryInfoVO> inventoryInfoVOList = collect.stream()
                .map(i -> new InventoryInfoVO().setInventoryCode(i.getInventoryCode()).setInventoryQuantity(-1))
                .collect(Collectors.toList());

        salesStockChangeCoreHandler.saveSalesLevelStockChangeLog(null, DefinedSystem.GOODS_CENTER.ordinal(),
                ADD_VIRTUAL_SALES_STOCK.getCode(), inventoryInfoVOList, new ArrayList<>(), collect);

        return ReturnResponseBean.ok(true);
    }

    private List<StockInventoryUnreal> checkInventoryListIfExists(List<String> inventoryCodeList) {
        if (CollectionUtils.isEmpty(inventoryCodeList)) {
            throw new StockRuntimeException(JOIN_GOODS_CENTER_INVENTORY_IS_EMPTY_900801);
        }

        //查询虚拟表数据
        List<StockInventoryUnreal> list = stockInventoryUnrealService.list(
                Wrappers.lambdaQuery(StockInventoryUnreal.class).in(StockInventoryUnreal::getInventoryCode, inventoryCodeList));

        //数量相等直接返回
        if (list.size() == inventoryCodeList.size()) {
            return list;
        }

        List<String> notExistsInventoryCodeList = new ArrayList<>();
        for (String inventoryCode : inventoryCodeList) {
            StockInventoryUnreal stockInventoryUnreal = list.stream().filter(f -> f.getInventoryCode().equals(inventoryCode)).findFirst().orElse(null);
            if (stockInventoryUnreal == null) {
                notExistsInventoryCodeList.add(inventoryCode);
            }
        }

        List<GoodsCenterInventoryVO> inventoryList = stockInventoryRealMapper.getInventoryByInventoryCodeList(notExistsInventoryCodeList);
        if (CollectionUtils.isEmpty(inventoryList)) {
            throw new StockRuntimeException(JOIN_GOODS_CENTER_INVENTORY_IS_NOT_EXISTS_900802, String.format("货品编码不存在：%s", String.join(",", notExistsInventoryCodeList)));
        }

        if (notExistsInventoryCodeList.size() != inventoryList.size()) {
            List<String> collect = inventoryList.stream().map(GoodsCenterInventoryVO::getInventoryCode).filter(inventoryCode -> !notExistsInventoryCodeList.contains(inventoryCode)).collect(Collectors.toList());
            throw new StockRuntimeException(JOIN_GOODS_CENTER_INVENTORY_IS_NOT_EXISTS_900802, String.format("货品编码不存在：%s", String.join(",", collect)));
        }

        List<GoodsCenterInventoryVO> realInventory = inventoryList.stream().filter(GoodsCenterInventoryVO::isReal).collect(Collectors.toList());
        if (CollectionUtils.isNotEmpty(realInventory)) {
            throw new StockRuntimeException(JOIN_GOODS_CENTER_INVENTORY_IS_NOT_VIRTUAL_900803);
        }


        //虚拟类货品列表
        List<StockInventoryUnreal> unrealList = new ArrayList<>();

        List<StockInventoryReal> collect = inventoryList.stream().map(i -> {
                    StockInventoryReal stockInventoryReal = new StockInventoryReal()
                            .setInventoryId(i.getInventoryId())
                            .setInventoryCode(i.getInventoryCode())
                            .setGoodsId(i.getGoodsId())
                            .setSaleStockNum(CommonConstant.ZERO)
                            .setUsedStockNum(CommonConstant.ZERO)
                            .setStatus(FINISHED);

                    StockInventoryUnreal stockInventoryUnReal = new StockInventoryUnreal()
                            .setInventoryId(i.getInventoryId())
                            .setInventoryCode(i.getInventoryCode())
                            .setGoodsId(i.getGoodsId())
                            .setSaleStockNum(CommonConstant.ZERO)
                            .setStatus(FINISHED);
                    unrealList.add(stockInventoryUnReal);
                    return stockInventoryReal;
                }

        ).collect(Collectors.toList());

        //插入实物类货品
        //查看不在实物类货品表的货品
        List<StockInventoryReal> realList = stockInventoryRealService.list(Wrappers.lambdaQuery(StockInventoryReal.class).in(StockInventoryReal::getInventoryCode, notExistsInventoryCodeList));
        List<String> realInventoryCodeList = realList.stream().map(StockInventoryReal::getInventoryCode).collect(Collectors.toList());

        List<StockInventoryReal> saveRealList = collect.stream().filter(f -> !realInventoryCodeList.contains(f.getInventoryCode())).collect(Collectors.toList());
        if (CollectionUtils.isNotEmpty(saveRealList)) {
            stockInventoryRealService.saveBatch(collect);
        }
        //插入虚拟类货品
        stockInventoryUnrealService.saveBatch(unrealList);

        return stockInventoryUnrealService.list(
                Wrappers.lambdaQuery(StockInventoryUnreal.class).in(StockInventoryUnreal::getInventoryCode, inventoryCodeList));
    }

    /**
     * 减少一个虚拟可售库存
     *
     * @param inventoryCodeList
     * @return
     */
    @Override
    public ReturnResponseBean<Boolean> deleteVirtualSalesStockData(List<String> inventoryCodeList) {
        List<StockInventoryUnreal> inventoryUnrealList = checkInventoryListIfExists(inventoryCodeList);
        List<StockInventoryUnreal> collect = inventoryUnrealList.stream().map(i -> i.setSaleStockNum(Math.max((i.getSaleStockNum() - 1), 0))).collect(Collectors.toList());
        stockInventoryUnrealService.updateBatchById(collect);

        //记录日志
        List<InventoryInfoVO> inventoryInfoVOList = collect.stream()
                .map(i -> new InventoryInfoVO().setInventoryCode(i.getInventoryCode()).setInventoryQuantity(1))
                .collect(Collectors.toList());

        salesStockChangeCoreHandler.saveSalesLevelStockChangeLog(null, DefinedSystem.GOODS_CENTER.ordinal(),
                DELETE_VIRTUAL_SALES_STOCK.getCode(), inventoryInfoVOList, new ArrayList<>(), collect);

        return ReturnResponseBean.ok(true);
    }

    private boolean checkParamsIsCorrect(Long goodsId, Long inventoryId, String inventoryCode, int stockNumber) {
        return goodsId != null && inventoryCode != null && inventoryId != null && stockNumber >= 0;
    }
}
